﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.Data.SqlClient;
using System.IO;

namespace UDS.Build.Database
{
    public class AttachDatabase : DatabaseBuildTaskBase
    {
        private string dbFile;
        [Required]
        public string DBFile
        {
            get
            {
                return dbFile;
            }
            set
            {
                CheckSingleQuotes("DBFile", value);
                dbFile = value;
            }
        }

        private string logFile = null;
        public string LogFile
        {
            get
            {
                if (logFile == null)
                {
                    string ext = System.IO.Path.GetExtension(DBFile);
                    if (ext.ToUpper().Equals(".MDF"))
                    {
                        logFile = DBFile.Replace(ext, ".ldf");
                    }
                    else
                    {
                        logFile = DBFile + ".ldf";
                    }
                }
                return logFile;
            }
            set
            {
                CheckSingleQuotes("LogFile", LogFile);
                logFile = value;
            }
        }

        [Required]
        public string ShadowFolder
        {
            get;
            set;
        }

        public override bool Execute()
        {
            // Drop existing DB first
            UDS.Management.Data.Database CreateTestDatabase = new UDS.Management.Data.Database(SqlServerInstance, DatabaseName);
            Log.LogMessage(MessageImportance.High, "Dropping database {0} on server {1}", DatabaseName, SqlServerInstance);
            try
            {
                CreateTestDatabase.DropDatabase(DatabaseName);
            }
            catch (SqlException e)
            {
                Log.LogWarningFromException(e, true);
            }

            // Create ShadowFolder if necessary
            if (!Directory.Exists(ShadowFolder))
            {
                Directory.CreateDirectory(ShadowFolder);
            }

            Log.LogMessage(MessageImportance.High, "Copying database {0}, log {1} to shadow directory {2}", DBFile, LogFile, ShadowFolder);
            // Refresh the ShadowFolder
            // Copy the DB files into temporary names, otherwise we cannot use the same files for multiple DBs.
            string destDBFile = Path.Combine(ShadowFolder, DatabaseName + ".mdf");
            File.Copy(DBFile, destDBFile, true);
            string destLogFile = Path.Combine(ShadowFolder, DatabaseName + ".ldf");
            File.Copy(LogFile, destLogFile, true);
            File.SetAttributes(destDBFile, File.GetAttributes(destDBFile) & (~(FileAttributes.ReadOnly)));
            File.SetAttributes(destLogFile, File.GetAttributes(destLogFile) & (~(FileAttributes.ReadOnly)));

            try
            {
                using (SqlConnection conn = new SqlConnection(CreateTestDatabase.MasterDBConnectionString))
                {
                    Log.LogMessage(MessageImportance.High, "Attaching file {0}, log {1} on server {2} to database {3}", destDBFile, destLogFile, SqlServerInstance, DatabaseName);
                    conn.Open();
                    string cmdText = "CREATE DATABASE " + DatabaseName + " ON " +
                                        "(FILENAME='" + destDBFile + "') " +
                                        "LOG ON (FILENAME='" + destLogFile + "') " +
                                        "FOR ATTACH_REBUILD_LOG";
                    SqlCommand cmd = new SqlCommand(cmdText, conn);
                    cmd.ExecuteNonQuery();

                    //
                    //  Set AUTO_CLOSE OFF
                    //
                    cmdText = String.Format("ALTER DATABASE {0} SET AUTO_CLOSE OFF", DatabaseName);
                    cmd = new SqlCommand(cmdText, conn);
                    cmd.ExecuteNonQuery();
                }
            }
            catch (SqlException e)
            {
                Log.LogErrorFromException(e, true, true, DBFile);
                return false;
            }
            return true;
        }
    }
}
